package handler

import (
	"database/sql/driver"
	"fmt"
	"log"
	"strconv"
	"time"

	"github.com/golang-jwt/jwt/v4"
	"github.com/quarkcloudio/quark-go/v2/pkg/builder"
	"github.com/quarkcloudio/quark-go/v2/pkg/dal/db"
	MD5Plugins "github.com/wsl/hi-go/plugins/md5"
	tokenManager "github.com/wsl/hi-go/plugins/token"
	"gorm.io/gorm"
)

// 自定义时间（重写JSON输出、数据库写入、数据库输出方法）
type LocalTime time.Time

func (t *LocalTime) MarshalJSON() ([]byte, error) {
	tTime := time.Time(*t)
	return []byte(fmt.Sprintf("\"%v\"", tTime.Format("2006-01-02 15:04:05"))), nil
}

func (t LocalTime) Value() (driver.Value, error) {
	var zeroTime time.Time
	tlt := time.Time(t)
	//判断给定时间是否和默认零时间的时间戳相同
	if tlt.UnixNano() == zeroTime.UnixNano() {
		return nil, nil
	}
	return tlt, nil
}

func (t *LocalTime) Scan(v interface{}) error {
	if value, ok := v.(time.Time); ok {
		*t = LocalTime(value)
		return nil
	}
	return fmt.Errorf("can not convert %v to timestamp", v)
}

// 复用（分页参考）
func PageManager(page int, pageSize int) func(*gorm.DB) *gorm.DB {
	return func(db *gorm.DB) *gorm.DB {
		offset := (page - 1) * pageSize
		return db.Offset(offset).Limit(pageSize)
	}
}

type TransFormIntJudge func(int) bool

// 分页数据转换
func PageManagerGetQuery(c *builder.Context) (int, int) {
	page := TransFormInt(c.Query("page"), 1, func(i int) bool { return i > 0 })
	fmt.Println("%ld", page)

	pageSize := TransFormInt(c.Query("pageSize"), 20, func(i int) bool { return i > 0 })
	fmt.Println("%ld", pageSize)
	return page, pageSize
}

// 默认转整型
func TransFormInt(num interface{}, defaultNum int, judge TransFormIntJudge) int {
	if num == nil {
		return defaultNum
	}
	if tidyNum, err := strconv.Atoi(num.(string)); err != nil {
		return defaultNum
	} else {
		if judge(tidyNum) {
			return tidyNum
		} else {
			return defaultNum
		}
	}
}

type AutoList[T interface{}] struct {
	list  []T
	totle int64
}

type User struct {
	Id        int            `json:"id" gorm:"autoIncrement"`
	Name      string         `json:"name"`
	Password  string         `json:"-"`
	Status    int            `json:"status" gorm:"default:1"`
	CreatedAt *LocalTime     `json:"created_at"`
	UpdatedAt *LocalTime     `json:"updated_at"`
	DeletedAt gorm.DeletedAt `json:"-"`
}

func (user *User) Hello(c *builder.Context) error {
	param := &User{}
	c.Bind(&param)
	name := c.Query("name")
	log.Println(c.Path())
	return c.JSONOk("操作成功", map[string]interface{}{
		"name": name,
	})
}

// 接口（这个其实把服务层跟业务层分开）
func (user *User) Login(c *builder.Context) error {
	username := c.Query("username").(string)
	err := user.delete(username)
	if err != nil {
		return c.JSONOk("已处理", map[string]interface{}{
			"result": "创建用户失败",
		})
	} else {
		return c.JSONOk("已处理", map[string]interface{}{
			"result": "创建用户完成",
		})
	}
}

// 查询用户列表
func (user *User) UserIndex(c *builder.Context) error {
	page, pageSize := PageManagerGetQuery(c)
	result, err := user.index(page, pageSize)
	if err != nil {
		return c.JSONOk("已处理", map[string]interface{}{
			"result": err.Error(),
		})
	} else {
		return c.JSONOk("已处理", map[string]interface{}{
			"list":  result.list,
			"totle": result.totle,
		})
	}
}

// 新增
func (user *User) Create(c *builder.Context) error {
	err := user.create(c.Query("name").(string), c.Query("password").(string))
	if err != nil {
		return c.JSONOk("已处理", map[string]interface{}{
			"result": err.Error(),
		})
	} else {
		return c.JSONOk("已处理", map[string]interface{}{
			"result": "创建成功",
		})
	}
}

func (p *User) create(username string, password string) error {
	password = (&MD5Plugins.MD5Manager{}).TransformStringToMD5(password)
	user := User{Name: username, Password: password}
	err := db.Client.Model(&p).Create(&user).Error
	return err
}

// 删除
func (p *User) delete(username string) error {
	// Unscoped 表示彻底删除 没有 Unscoped 表示软删除
	err := db.Client.Model(&p).Unscoped().Where("name = ?", username).Delete(&p).Error
	return err
}

// 改
func (user *User) Update(c *builder.Context) error {
	err := user.update(c.Query("name").(string))
	if err != nil {
		return c.JSONOk("已处理", map[string]interface{}{
			"result": err.Error(),
		})
	} else {
		return c.JSONOk("已处理", map[string]interface{}{
			"result": "更新成功",
		})
	}
}

func (p *User) update(username string) error {
	user := User{Name: "new_" + username}
	err := db.Client.Model(&p).Where("name = ?", username).Updates(&user).Error
	return err
}

// 查
func (p *User) index(page int, pageSize int) (AutoList[*User], error) {
	var users []*User
	// err := db.Client.Model(&p).Select("name", "id").Find(&users).Error
	// Scopes 公用代码块
	query := db.Client.Model(&p)
	var count int64 = 0
	err := query.Scopes(PageManager(page, pageSize)).Unscoped().Find(&users).Count(&count).Error
	return AutoList[*User]{users, count}, err
}

// 获取jwt Token
func (p *User) GetToken(c *builder.Context) error {
	tokenString := (&tokenManager.AdminClaims{}).CreateJWTToken(123)
	return c.JSONOk("获取成功", map[string]interface{}{
		"token": tokenString,
	})
}

// 解析 token
func (p *User) ParseToken(c *builder.Context) error {
	if tokenString, ok := c.Query("token").(string); !ok {
		panic("无效 token")
	} else {
		id := (&tokenManager.AdminClaims{}).ParseJWTToken(tokenString)
		return c.JSONOk("获取成功", map[string]interface{}{
			"id": id,
		})
	}
}

// 解析 token
func (p *User) ParseTokenHeader(c *builder.Context) error {
	type UserClaims struct {
		Id int `json:"id"`
		jwt.RegisteredClaims
	}
	tokenString := c.Token()
	if tokenString == "" {
		return c.JSONError("获取token失败")
	}
	result, err := jwt.ParseWithClaims(tokenString, &UserClaims{}, func(token *jwt.Token) (interface{}, error) {
		return []byte("123456"), nil
	})
	claims := result.Claims.(*UserClaims)
	if err != nil {
		return c.JSONError("操作失败")
	} else {
		return c.JSONOk("获取成功", map[string]interface{}{
			"id": claims.Id,
		})
	}
}

// web页面
func (p *User) HomeIndex(c *builder.Context) error {
	return c.Render(200, "index.html", map[string]interface{}{
		"index": "曾经年少",
	})
}

// 资源动态路由
func (p *User) ResourceDynamic(c *builder.Context) error {
	return c.JSON(200, map[string]interface{}{
		"code": 401,
		"msg":  "请重新登陆",
	})
}
